package com.hackaton.touringengine;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.jdo.JDOObjectNotFoundException;
import javax.jdo.PersistenceManager;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.repackaged.org.json.JSONArray;
import com.google.appengine.repackaged.org.json.JSONException;
import com.google.appengine.repackaged.org.json.JSONObject;
import com.hackaton.touringengine.entity.Location;
import com.hackaton.touringengine.entity.User;
import com.hackaton.touringengine.persistence.PersistenceFactory;

@SuppressWarnings("serial")
public class CheckinServlet extends HttpServlet {
	private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		PersistenceManager pm = PersistenceFactory.get().getPersistenceManager();
		final String post = req.getParameter("post");
		try {
			JSONObject jsonObject = new JSONObject(post);
			final String deviceId = jsonObject.getString("deviceId");
			if (deviceId == null) {
				throw new RuntimeException("deviceId should not be null");
			}
	    	final String name = jsonObject.getString("name");
	    	if (name == null) {
				throw new RuntimeException("user name should not be null");		    		
	    	}
		    JSONArray locationArray = jsonObject.getJSONArray("locations");
			    //persisting user locations 
	    	final int length = locationArray.length();
    		List<Location> locations = new ArrayList<Location>(length);
		    for (int i = 0; i < length; ++i) {
		    	JSONObject locationObject = locationArray.getJSONObject(i);
		    	final double latitude = locationObject.getDouble("latitude");	
		    	final double longitude = locationObject.getDouble("longitude");
		    	final Date time = TIME_FORMAT.parse(locationObject.getString("time"));
		    	final Double accuracy = locationObject.optDouble("accuracy");
		    	final Double velocity = locationObject.optDouble("velocity");
		    	Location location = new Location();
		    	location.setDate(time);
		    	location.setLatitude(latitude);
		    	location.setLongitude(longitude);
		    	if (accuracy.equals(Double.NaN)) {
			    	location.setAccuracy(null);
		    	} else {
			    	location.setAccuracy(accuracy);
		    	}
		    	if (velocity.equals(Double.NaN)) {
			    	location.setVelocity(null);
		    	} else {
			    	location.setVelocity(velocity);
		    	}
		    	locations.add(location);
		    }

		    Key userKey = KeyFactory.createKey(User.class.getSimpleName(), deviceId);
		    User user = null;
		    try {
		    	user = pm.getObjectById(User.class, userKey);
		    	if (!user.getName().equals(name)) {
		    		user.setName(name);
		    	}
		        user.getLocations().addAll(locations);
		    } catch (JDOObjectNotFoundException notFoundE) {
		    	//user not found, we should create it
		        Key key = KeyFactory.createKey(User.class.getSimpleName(), deviceId);
		        user = new User();
		        user.setKey(key);
		        user.setName(name);
		        user.setLocations(locations);
		        pm.makePersistent(user);		    	
		    }
		    writeResult(resp, 0);
		} catch (Exception e) {
			writeResult(resp, 1);
		} finally {
			pm.close();
		}
	}

	private void writeResult(HttpServletResponse resp, int resultCode) throws IOException {
		resp.setContentType("text/plain");
		JSONObject resultJSON = new JSONObject();
		JSONObject statusJSON = new JSONObject();
		try {
			statusJSON.put("code", resultCode);
			resultJSON.put("status", statusJSON);
			resp.setStatus(200);
			resp.getWriter().println(resultJSON.toString());
		} catch (JSONException e1) {
			//this won't happen
		}
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		doGet(req, resp);
	}

}
